home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
cuj9204
/
1004060a
< prev
next >
Wrap
Text File
|
1992-06-02
|
9KB
|
326 lines
/* @(#) money.h Copymiddle 1991 Adolfo Di Mare */
/* */
/* Yet Another Money C++ Class */
/* */
/* Use freely but acknowledge author and publication. */
/* DO NOT SELL IT. The author reserves all rigths! */
/* BITNET: adimare@UCRVM2 */
/* Compiler: Borland C++ v 2.0 */
/* [should work with Turbo C++] */
#ifndef _money_h
#define _money_h
extern "C" { // avoid type clashes with the C library
#include <math.h> /* floor() */
#include <float.h> /* DBL_DIG */
}
#ifndef MONEY_DECIMALS /* number of decimals in */
#define MONEY_DECIMALS 2 /* any money quantity */
#endif /* don't use parentesis! */
#define __VAL(n) n /* 1 level indirection */
#define TENPOW(n) __VAL(1.0e##n) /* Trick to yield 10^n */
#define MONEY_DIG DBL_DIG
class money {
public:
static int decimals() { return MONEY_DECIMALS; }
static int digits() { return MONEY_DIG; }
static double SCALE()
{ return TENPOW(MONEY_DECIMALS); }
money(); // do nothing constructor
money(double); // constructor from double
money(const money&); // copy constructor
money& operator= (const money&); // copy operator
money& operator= (double); // copy from double
operator double() const; // convert to double
int OK() const; // check money's invariant
void FIX(); // get rid of unwanted decimals
friend money operator + (const money&, const money&);
friend money operator + (double, const money&);
friend money operator + (const money&, double);
friend money operator - (const money&, const money&);
friend money operator - (double, const money&);
friend money operator - (const money&, double);
friend money operator* (const money&, double);
friend money operator* (double, const money&);
friend double operator/ (const money&, const money&);
friend money operator/ (const money&, double);
friend money operator% (const money&, const money&);
// money * money is NOT valid
// double / money is INVALID
friend int operator == (const money&, const money&);
friend int operator != (const money&, const money&);
friend int operator < (const money&, const money&);
friend int operator > (const money&, const money&);
friend int operator <= (const money&, const money&);
friend int operator >= (const money&, const money&);
money& operator += (const money&);
money& operator += (double);
money& operator -= (const money&);
money& operator -= (double);
money& operator *= (double);
money& operator /= (double);
friend money operator+ (const money&);
friend money operator- (const money&);
money& operator++();
money& operator--();
friend int operator! (const money&);
friend money abs(const money&);
friend money flatten(
const money& m,
double cents=0.25, int rounding = 1 /* TRUE */);
protected: // let users change the class behaviour
double m_money;
};
// Constructors && assignment
inline money::money() {
// do nothing constructor, for efficiency
}
inline money::money(double d) {
// construct from double
m_money = d*SCALE();
FIX();
}
inline money::money(const money& m) {
// copy constructor
m_money = m.m_money;
}
inline money& money::operator= (const money& m) {
// copy operator
m_money = m.m_money;
return *this;
}
inline money& money::operator= (double d) {
// assign from double
m_money = d*SCALE();
FIX();
return *this;
}
inline money::operator double() const {
// convert to double
return m_money / SCALE();
}
inline int money::OK() const {
// Returns TRUE (1) when the quantity stored
// in *this really corresponds to a money
// quantity.
money temp;
temp.m_money = m_money;
temp.FIX();
return (
( temp.m_money == m_money )
&&
( fabs(m_money) < (TENPOW(DBL_DIG) / SCALE()) )
);
}
inline void money::FIX() {
// Deletes all decimals digits beyond
// the MONEY_DECIMALS decimal place.
// - If the value is out of range, FIX
// won't fix it.
m_money =
(m_money > 0.0
?
floor(
m_money
#ifdef MONEY_ROUNDING
+ 0.5 // 0.49 is also an option...
#endif
)
:
ceil(
m_money
#ifdef MONEY_ROUNDING
- 0.5
#endif
)
);
}
// add
inline money operator+ (const money& m, const money& mm) {
money temp; // don't mult*SCALE()
temp.m_money = m.m_money + mm.m_money;
return temp;
}
inline money operator+ (double d, const money& m) {
return (money(d)+m);
}
inline money operator+ (const money& m, double d) {
return (m+money(d));
}
// substract
inline money operator- (const money& m, const money& mm) {
money temp;
temp.m_money = m.m_money - mm.m_money;
return temp;
}
inline money operator- (double d, const money& m) {
return (money(d)-m);
}
inline money operator- (const money& m, double d) {
return (m-money(d));
}
// multiply
inline money operator* (const money& m, double d) {
money temp;
temp.m_money = m.m_money * d; // don't mult by SCALE()
temp.FIX(); // this could be delayed...
return temp;
}
inline money operator* (double d, const money& m) {
return (m*d);
}
// divide
inline double operator/ (const money& m, const money& mm) {
return m.m_money / mm.m_money;
}
inline money operator/ (const money& m, double d) {
money temp;
temp.m_money = m.m_money / d;
temp.FIX(); // this could be delayed...
return temp;
}
inline money operator% (const money& m, const money& mm) {
money temp;
temp.m_money = fmod(m.m_money, mm.m_money);
temp.FIX(); // this could be delayed...
return temp;
}
// compare
inline int operator == (const money& m, const money& mm) {
return m.m_money == mm.m_money;
}
inline int operator != (const money& m, const money& mm) {
return m.m_money != mm.m_money;
}
inline int operator < (const money& m, const money& mm) {
return m.m_money < mm.m_money;
}
inline int operator > (const money& m, const money& mm) {
return m.m_money > mm.m_money;
}
inline int operator <= (const money& m, const money& mm) {
return m.m_money <= mm.m_money;
}
inline int operator >= (const money& m, const money& mm) {
return m.m_money >= mm.m_money;
}
inline money& money::operator += (const money& m) {
m_money += m.m_money;
return *this;
}
inline money& money::operator += (double d) {
m_money += d*SCALE();
FIX();
return *this;
}
inline money& money::operator -= (const money& m) {
m_money -= m.m_money;
return *this;
}
inline money& money::operator -= (double d) {
m_money -= d*SCALE();
FIX();
return *this;
}
inline money& money::operator *= (double d) {
m_money *= d;
FIX();
return *this;
}
inline money& money::operator /= (double d) {
m_money /= d;
FIX();
return *this;
}
// unary op's
inline money operator+(const money& m) {
return m;
}
inline money operator-(const money& m) {
money temp;
temp.m_money = -m.m_money;
return temp;
}
inline money& money::operator++() {
m_money += SCALE();
#if (MONEY_DECIMALS<0)
FIX(); // avoid problems because of
#endif // the representation of 10^-n
return *this;
}
inline money& money::operator--() {
m_money -= SCALE();
#if (MONEY_DECIMALS<0)
FIX();
#endif
return *this;
}
inline int operator!(const money& m) {
return m.m_money == 0.0;
}
inline money abs(const money& m) {
money temp;
temp.m_money = fabs(m.m_money);
return temp;
}
money flatten(const money& m, double cents, int rounding) {
// Returns a money data item where the cents are
// rounded modulo "cents". In this way cents can
// be stripped of money items when the currency
// does not have all the coins required to pay
// every posible quantity.
money temp;
double c = floor(fabs(cents*money::SCALE())); // cents
double r = fmod(m.m_money, c); // remainder
temp.m_money =
(!rounding || (2.0* r <= c)
? m.m_money - r
: m.m_money - r + c
);
return temp;
}
/* Avoid name space overcrowding */
#undef __VAL
#undef TENPOW /* jic: Just In Case! */
#endif /* _money_h */